package com.mic.yzzn.plc.core.control.datastructure;

import com.mic.yzzn.plc.common.control.datastructure.PLCCollectorControlCmd;
import com.mic.yzzn.plc.core.control.PLCCollectorImpl;
import com.mic.yzzn.plc.core.ins.toolUtils.PLCFileWatcher;
import com.mic.yzzn.plc.core.ins.toolUtils.PLC_XMLParser;
import com.mic.yzzn.plc.core.plcevents.PLCFileChangeEvent;
import com.mic.yzzn.plc.core.plcevents.PLCNewCollectorEvent;
import com.mic.yzzn.plc.core.plcevents.listener.PLCFileChangeEventListener;
import com.mic.yzzn.plc.core.plcevents.listener.PLCNewCollectorEventListener;

import java.io.Serializable;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * PLC 采控上下文类
 */
public class PLCContext implements PLCFileChangeEventListener, Serializable
{
	/** Worker线程Map */
	private ConcurrentHashMap<String, PLCCollectorImpl> collectors = new ConcurrentHashMap<String, PLCCollectorImpl>();
	/** 文件监听器 */
	private PLCFileWatcher fileWatcher;
	/** PLC配置文件解析器 */
	private PLC_XMLParser xmlParser;
	/** XML文件名 */
	private String configFileName;
	/** PLC配置 */
	private PLCConfig config = new PLCConfig();
	/** 新采集器事件监听者 */
	private CopyOnWriteArrayList<PLCNewCollectorEventListener> newCollectorEventListeners = new CopyOnWriteArrayList<PLCNewCollectorEventListener>();
	
	// 初始化方法
	@SuppressWarnings("unused")
	private PLCContext()
	{
		
	}
	
	public PLCContext(String configFilePath, String configFileNmae)
	{
		// 初始化文件监听器
		fileWatcher = new PLCFileWatcher(configFilePath);
		fileWatcher.addListener(this);
		// 初始化XML解析器
		xmlParser = new PLC_XMLParser();
		// 记录配置文件名
		this.configFileName = configFileNmae;
	}
	
	/**
	 * 暂停所有的采集器
	 */
	public void pauseAllCollectors()
	{
		if (collectors.isEmpty())
		{
			return;
		}
		
		Set<String> keys = collectors.keySet();
		
		for(Iterator<String> iterator = keys.iterator(); iterator.hasNext();)
		{
			String key = iterator.next();
			PLCCollectorImpl collector = collectors.get(key);
			collector.setAsleep(true);
		}
	}
	
	/**
	 * 唤醒所有的采集器(暂停中)
	 */
	public void wakeAllCollectors()
	{
		if (collectors.isEmpty())
		{
			return;
		}
		
		Set<String> keys = collectors.keySet();
		
		for(Iterator<String> iterator = keys.iterator(); iterator.hasNext();)
		{
			String key = iterator.next();
			PLCCollectorImpl collector = collectors.get(key);
			collector.setAsleep(false);
		}
	}
	
	/**
	 * 向RMI注册所有的采集器
	 */
	public void rebindAllCollector()
	{
		if (collectors.isEmpty())
		{
			return;
		}
		
		Set<String> keys = collectors.keySet();
		
		for(Iterator<String> iterator = keys.iterator(); iterator.hasNext();)
		{
			String key = iterator.next();
			PLCCollectorImpl collector = collectors.get(key);
			String name = collector.getStationConfig().id();
			System.out.println(name);
			try
			{
				// 向服务器注册RMI
				Naming.rebind(name, collector);
			} 
			catch (Exception e)
			{
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * 从XML配置文件中激活并开始工作
	 */
	public void setFromConfigXML()
	{
		// 开始监听文件
		fileWatcher.startWatch();
		
		// 解析XML文件
		try
		{	
			setupWithXML(true);	
		} 
		catch (Exception e)
		{
			e.printStackTrace();
		}
	}
	
	/**
	 * 激活所有的采集器
	 */
	public void fireAllCollector()
	{
		if (collectors.isEmpty())
		{
			return;
		}
		
		Set<String> keys = collectors.keySet();
		
		for(Iterator<String> iterator = keys.iterator(); iterator.hasNext();)
		{
			String key = iterator.next();
			PLCCollectorImpl collector = collectors.get(key);
			collector.startToWork();
		}
	}
	
	
	/**
	 * 获取指定ID的采集器
	 * @param ID
	 * @return
	 */
	public PLCCollectorImpl getCollectorWithID(String ID)
	{
		return this.collectors.get(ID);
	}
	
	/**
	 * 获取所有的采集器
	 * @return
	 */
	public ArrayList<PLCCollectorImpl> getAllCollectors()
	{
		Set<String> allkeys = this.collectors.keySet();
		ArrayList<PLCCollectorImpl> collectorsArray = new ArrayList<PLCCollectorImpl>();
		
		for (Iterator<String> i = allkeys.iterator(); i.hasNext();)
		{
			PLCCollectorImpl collector = this.collectors.get(i.next());
			collectorsArray.add(collector);
		}
		
		return collectorsArray;
	}
	
	/**
	 * 添加新的新采集器事件监听者
	 * @param listener
	 */
	public void addNewCollectorEventListener(PLCNewCollectorEventListener listener)
	{
		newCollectorEventListeners.add(listener);
	}
	
	/**
	 * 移除新采集器事件监听者
	 * @param listener
	 * @return
	 */
	public boolean removeNewCollectorEventListeners(PLCNewCollectorEventListener listener)
	{
		return newCollectorEventListeners.remove(listener);
	}
	
	// Getter
	public ConcurrentHashMap<String, PLCCollectorImpl> getCollectors()
	{
		return collectors;
	}
	
	public PLCFileWatcher getFileWatcher()
	{
		return fileWatcher;
	}
	
	public String getConfigFileName()
	{
		return configFileName;
	}
	
	/**
	 * 获取XML配置文件的路径
	 * @return 配置文件的路径
	 */
	private String getXMLFilePath()
	{
		String filePath = (fileWatcher.getWatchPath().length() > 0) ? fileWatcher.getWatchPath() + "/" : "";
		filePath += configFileName;
		
		return filePath;
	}
	
	/**
	 * 根据XML读取器中的信息配置采集器
	 * @param isInit 是否是第一次配置
	 */
	private void setupCollectorsFromXMLParser(boolean isInit)
	{
		// 如果是第一次初始化
		if (isInit)
		{
			Set<String> keySet = xmlParser.getStationConfigMap().keySet();
			
			for (Iterator<String> i = keySet.iterator(); i.hasNext() ;)
			{
				String key = i.next();
				PLCStationConfig stationConfig = xmlParser.getStationConfigMap().get(key);
				try
				{
					PLCCollectorImpl collector = new PLCCollectorImpl(stationConfig);
					collector.setConfig(config);
					this.collectors.put(collector.getCollectorNumber(), collector);
					notifyAllNewCollectorListener(collector);
				} 
				catch (RemoteException e)
				{
					e.printStackTrace();
				} catch (Exception e) {
					e.printStackTrace();
				}

			}
		}
		else // 在运行的过程中更改了配置
		{
			Set<String> keySet = xmlParser.getStationConfigMap().keySet();
			
			for (Iterator<String> i = keySet.iterator(); i.hasNext() ;)
			{
				String key = i.next();
				PLCStationConfig stationConfig = xmlParser.getStationConfigMap().get(key);
				PLCCollectorImpl collector = collectors.get(stationConfig.id());
				if (collector == null) // 创建新的采集器
				{
					try
					{
						collector = new PLCCollectorImpl(stationConfig);
						collector.setConfig(config);
						this.collectors.put(collector.getCollectorNumber(), collector);
						notifyAllNewCollectorListener(collector);
						collector.startToWork();
					} 
					catch (RemoteException e)
					{
						e.printStackTrace();
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
				else // 如果已经存在
				{
					if (stationConfig.overdue) // 如果是过期的配置则将采集器移除
					{
						collector.setConfig(config);
						// 停止采集器
						collector.stopWork();
					}
					else
					{
						if (!stationConfig.updateTime.before(collector.stationConfigTimestamp()))
						{
							collector.setConfig(config);
							collector.replaceStationConfig(stationConfig);
							if (collector.isStop())
							{
								collector.startToWork();
							}
						}
					}
				}
			}
		}
	}
	
	/**
	 * XML配置文件更改后的响应方法
	 */
	private void setupWithXML(boolean isInit)
	{
		try
		{
			// 如果不是正在读写则等待
			while(xmlParser.isReading())
			{

			}
			xmlParser.parseXMLFileFromURI(getXMLFilePath());
			// 更新配置文件和收集器
			config = xmlParser.getConfig();
			// 设置采集器配置
			setupCollectorsFromXMLParser(isInit);
		} 
		catch (Exception e)
		{
			e.printStackTrace();
		}
	}

	/**
	 * 文件改变监听方法
	 */
	@Override
	public void notifyFileChange(PLCFileChangeEvent event)
	{
		if (event.getFileName().equals("PLC-Config.xml"))
		{
			setupWithXML(false);
		}
	}
	
	/**
	 * 通知新采集器事件监听者
	 * @param newCollector
	 */
	private void notifyAllNewCollectorListener(PLCCollectorImpl newCollector)
	{
		// 通知监听者
		for (PLCNewCollectorEventListener listener : newCollectorEventListeners)
		{
			listener.notifyNewCollectorAdded(new PLCNewCollectorEvent(this, newCollector));
		}
	}

	/**
	 * 控制采集器的状态
	 * @param cmd 控制命令
	 * @return 控制结果
     */
	public int controlCollector(PLCCollectorControlCmd cmd)
	{
		String targetId = cmd.getTargetID();

		PLCCollectorImpl targetCollector = collectors.get(targetId);

		// 如果等于空则返回的是错误的ID
		if (collectors == null)
		{
			return PLCCollectorControlCmd.PLCCollectorControlCmdResultWrongID;
		}
		else
		{
            // 判断是否有执行延迟
            if (cmd.getDelay() != 0)
            {
                try
                {
                    Thread.sleep(cmd.getDelay() * 1000);
                }
                catch (Exception e)
                {
                    e.printStackTrace();
                }
            }

			if (cmd.getType() == PLCCollectorControlCmd.PLCCmdTypeActivation)
			{
				// 处于停止状态
				if (targetCollector.isStop())
				{
					// 处于停止状态的采集器只支持重启
					return PLCCollectorControlCmd.PLCCollectorControlCmdResultUnsuitCmd;
				}

				// 处于睡眠状态
				if (targetCollector.isAsleep())
				{
					targetCollector.setAsleep(false);
				}
				else // 处于活跃状态
				{
					return PLCCollectorControlCmd.PLCCollectorControlCmdResultUnnecessary;
				}

                System.out.println("启动采集器");
				return PLCCollectorControlCmd.PLCCollectorControlCmdResultSuccess;
			}
			else if (cmd.getType() == PLCCollectorControlCmd.PLCCmdTypeSleep)
			{
				// 处于停止状态
				if (targetCollector.isStop())
				{
					// 处于停止状态的采集器只支持重启
					return PLCCollectorControlCmd.PLCCollectorControlCmdResultUnsuitCmd;
				}
				
				// 不处于睡眠状态
				if (!targetCollector.isAsleep())
				{
					targetCollector.setAsleep(true);
				}
				else // 已经处于睡眠状态
				{
					return PLCCollectorControlCmd.PLCCollectorControlCmdResultUnnecessary; 
				}

                System.out.println("休眠采集器");
				return PLCCollectorControlCmd.PLCCollectorControlCmdResultSuccess;
			}
			else if (cmd.getType() == PLCCollectorControlCmd.PLCCmdTypeStop)
			{
				// 不处于停止状态
				if (!targetCollector.isStop())
				{
					targetCollector.setAsleep(false); // 停止睡眠
					targetCollector.stopWork();
				}
				else // 已经处于停止状态 
				{
					return PLCCollectorControlCmd.PLCCollectorControlCmdResultUnnecessary; 
				}

                System.out.println("停止采集器");
				return PLCCollectorControlCmd.PLCCollectorControlCmdResultSuccess;
			}
			else if (cmd.getType() == PLCCollectorControlCmd.PLCCmdTypeReboot)
			{
				// 重建线程
				targetCollector.stopWork();

				// 获取当前线程的配置
				PLCStationConfig stationConfig = targetCollector.getStationConfig();

				try
				{
					targetCollector = new PLCCollectorImpl(stationConfig);
					targetCollector.setConfig(config);
					collectors.put(targetId, targetCollector);
					// 通知新监听者
					notifyAllNewCollectorListener(targetCollector);
					targetCollector.startToWork();
				}
				catch (Exception e)
				{
					e.printStackTrace();
					return PLCCollectorControlCmd.PLCCollectorControlCmdResultFail;
				}

                System.out.println("重启采集器");
				return PLCCollectorControlCmd.PLCCollectorControlCmdResultSuccess;
			}
		}

		return PLCCollectorControlCmd.PLCCollectorControlCmdResultFail;
	}
}
